package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.article.mapper.ArticleContentMapper;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.article.service.ArticleService;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.common.constants.ArticleConstants;
import com.heima.model.search.dtos.SearchArticleVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * TODO
 *
 * @Author mr.zhao
 * @Date 2025/6/25 15:35
 */
@Service
@Slf4j
@Transactional
public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {
	@Autowired
	private ArticleContentMapper articleContentMapper;
	@Autowired
	private Configuration configuration;
	@Autowired
	private FileStorageService fileStorageService;
	@Autowired
	private ArticleService articleService;

	/**
	 * 生成静态化页面
	 *
	 * @param apArticle
	 * @param content
	 */
	@Async
	@Override
	public void buildArticleToMinio(ApArticle apArticle, String content) {
		if (StringUtils.isNotBlank(content)){
			//1. 文章内容通过freemarker生成静态html页面
			Template template = null;
			//2. 输出流
			StringWriter writer = new StringWriter();
			try {
				template = configuration.getTemplate("article.ftl");
				//2.1 创建模型
				Map<String, Object> contentDataModel = new HashMap<>();
				//content是固定的,因为article.ftl中有<#if content??>${content}</#if>
				//因为apArticleContent.getContent()获取的是字符串,所以需要转换成对象
				contentDataModel.put("content", JSONArray.parseArray(content));
				//2.2 合成方法
				template.process(contentDataModel,writer);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
			//3. 把静态页面上传到MinIO
			//3.1 文件流
			ByteArrayInputStream inputStream = new ByteArrayInputStream(writer.toString().getBytes());
			String path = fileStorageService.uploadHtmlFile("", apArticle.getId() + ".html", inputStream);
			//4. 把静态页面的路径保存到数据库
			articleService.update(Wrappers.<ApArticle>lambdaUpdate()
					.eq(ApArticle::getId,apArticle.getId())
					.set(ApArticle::getStaticUrl,path)
			);
			//5. 发送到rabbitmq,创建es索引
			createArticleESIndex(apArticle,content,path);
		}
	}

	@Autowired
	private RabbitTemplate rabbitTemplate;

	/**
	 * 创建文章索引
	 * @param apArticle
	 * @param content
	 * @param path
	 */
	private void createArticleESIndex(ApArticle apArticle, String content, String path) {
		SearchArticleVo searchArticleVo = new SearchArticleVo();
		BeanUtils.copyProperties(apArticle,searchArticleVo);
		searchArticleVo.setContent(content);
		searchArticleVo.setStaticUrl(path);

		rabbitTemplate.convertAndSend(ArticleConstants.ARTICLE_ES_SYNC_TOPIC,ArticleConstants.ARTICLE_ES_SYNC_ROUTINGKEY, JSON.toJSONString(searchArticleVo));
	}
}
